# coding = utf-8
from django.db.models import Sum
from rest_framework import serializers
from rest_framework.serializers import ModelSerializer, ListSerializer

from finance.models import Job, AccountTitle, Employee, Customer, Bank, CasePerson, CaseLawyer, SaleOrder, Receipt, \
    Expense, ProfitRule, OtherIncome, PaymentDetail, PaymentOrder, Journal, InitAccount, PayOrder, BorrowLend, FundBill, \
    RepaymentBill, AccountCode, BusinessFee


class JobSerializer(ModelSerializer):
    """职务类型"""
    class Meta:
        model = Job
        fields = '__all__'


class AccountCodeSerializer(ModelSerializer):
    """基础科目编码"""

    class Meta:
        model = AccountCode
        fields = ['code', 'name']


class AccountTitleSerializer(ModelSerializer):
    """会计科目"""
    children = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = AccountTitle
        fields = ['id', 'name',  'parent', 'code', 'desc', 'children']

    def get_children(self, obj):
        if obj.children.count() == 0:
            return ""
        return self.__class__(obj.children.all(), many=True).data


class AccountTitleListSerializer(ModelSerializer):
    """会计科目"""

    class Meta:
        model = AccountTitle
        fields = ['id', 'name',  'parent', 'desc']


class EmployeeSerializer(ModelSerializer):
    """员工信息"""
    job_name = serializers.CharField(source="job.name", read_only=True)

    class Meta:
        model = Employee
        exclude = ['update_at', 'create_at']


class CasePersonSerializer(ModelSerializer):
    """案件相关人员"""
    class Meta:
        model = CasePerson
        exclude = ["update_at", "create_at"]


class LawyerListSerializer(ListSerializer):

    def update(self, instance, validated_data):
        """
           instance: 要更新的对象们
           validated_data： 更新的数据们
           通过self.child可以访问绑定的ModelSerializer
           """
        # Maps for id->instance and id->data item.
        obj_mapping = {obj.id: obj for obj in instance}
        data_mapping = {data['id']: data for data in validated_data if data.get("id", None)}
        add_data = [data for data in validated_data if data.get("id", None) is None]
        # Perform creations and updates.
        ret = []
        for data_id, data in data_mapping.items():
            obj = obj_mapping.get(data_id, None)
            if obj is None:
                ret.append(self.child.create(data))
            else:
                ret.append(self.child.update(obj, data))

        # Perform creations
        for obj in add_data:
            ret.append(self.child.create(obj))
        # Perform deletions.
        # for obj_id, obj in obj_mapping.items():
        #     if obj_id not in data_mapping:
        #         obj.delete()

        return ret


class CaseLawyerSerializer(ModelSerializer):
    """负责律师"""
    id = serializers.IntegerField(required=False)
    lawyer = serializers.CharField(source="employee.name", read_only=True)
    post_name = serializers.CharField(source='get_post_display', read_only=True)
    case_name = serializers.CharField(source='customer.case_name', read_only=True)

    class Meta:
        model = CaseLawyer
        list_serializer_class = LawyerListSerializer
        exclude = ["update_at", "create_at"]


class CustomerSerializer(ModelSerializer):
    """客户资料"""
    persons = CasePersonSerializer(many=True, read_only=True)
    lawyers = CaseLawyerSerializer(many=True, read_only=True)
    cate_name = serializers.CharField(source='get_case_category_display', read_only=True)

    class Meta:
        model = Customer
        exclude = ['update_at', 'create_at']


class CustomerListSerializer(ModelSerializer):
    """客户资料"""
    class Meta:
        model = Customer
        fields = ['id', 'name', 'case_name', 'telephone', 'help_code']


class BankSerializer(ModelSerializer):
    """银行信息"""
    class Meta:
        model = Bank
        exclude = ['update_at', 'create_at']


class ReceiptSerializer(ModelSerializer):
    """收款单"""
    sale_order_name = serializers.CharField(source='sale_order.customer', read_only=True)
    sale_order_no = serializers.CharField(source='sale_order.order_no', read_only=True)
    account_name = serializers.CharField(source='acc_title.name', read_only=True)
    user_name = serializers.CharField(source='user.real_name', read_only=True)
    handler_name = serializers.CharField(source='handler.name', read_only=True)
    acc_type_name = serializers.CharField(source='account_type.account', read_only=True)
    debt = serializers.SerializerMethodField()

    class Meta:
        model = Receipt
        exclude = ['update_at', 'create_at']

    def get_debt(self, obj):
        if obj.paid_money is None:
            return obj.recv_money
        return obj.recv_money - obj.paid_money


class PaymentDetailSerializer(ModelSerializer):
    """支付明细表"""
    lawyer_name = serializers.CharField(source='lawyer.name', read_only=True)
    post_name = serializers.CharField(source='get_post_display', read_only=True)
    order_time = serializers.CharField(source='payment.order_time', read_only=True)
    order_no = serializers.CharField(source='payment.order_no', read_only=True)
    acc_title_name = serializers.CharField(source='acc_title.name', read_only=True)
    account_name = serializers.CharField(source='account_type.account', read_only=True)

    class Meta:
        model = PaymentDetail
        fields = ['id', 'payment', 'lawyer', 'lawyer_name', 'post', 'post_name', 'acc_title_name', 'account_name', 'ratio', 'money', 'desc', 'order_time', 'order_no']


class PaymentOrderSerializer(ModelSerializer):
    """支付表"""
    sale_order_name = serializers.CharField(source='sale_order.order_no', read_only=True)
    details = PaymentDetailSerializer(many=True)

    class Meta:
        model = PaymentOrder
        fields = ['id', 'order_no', 'sale_order', 'sale_order_name', 'customer_name', 'order_time', 'desc', 'user', 'details']

    def create(self, validated_data):
        details_data = validated_data.pop('details')
        payment = self.Meta.model.objects.create(**validated_data)
        for detail_data in details_data:
            PaymentDetail.objects.create(payment=payment, **detail_data)
        return payment

    def update(self, instance, validated_data):
        details_data = self.context["request"].data.get("details", None)
        validated_data.pop('details')
        instance.id = validated_data.get('id', instance.id)
        instance.order_no = validated_data.get('order_no', instance.order_no)
        instance.sale_order = validated_data.get('sale_order', instance.sale_order)
        instance.acc_title = validated_data.get('customer_name', instance.customer_name)
        instance.order_time = validated_data.get('order_time', instance.order_time)
        instance.desc = validated_data.get('desc', instance.desc)
        instance.user = validated_data.get('user', instance.user)
        instance.save()

        for detail in details_data:
            ids = detail.pop("id")
            defaults = {
                "payment_id": detail.get("payment"),
                "lawyer_id": detail.get("lawyer"),
                "ratio": detail.get("ratio"),
                "post": detail.get("post"),
                "money": detail.get("money"),
                "desc": detail.get("desc"),
            }
            PaymentDetail.objects.update_or_create(id=ids, defaults=defaults)
        return instance


class PayOrderListSerializer(serializers.ListSerializer):

    def update(self, instance, validated_data):
        """
           instance: 要更新的对象们
           validated_data： 更新的数据们
           通过self.child可以访问绑定的ModelSerializer
           """
        # Maps for id->instance and id->data item.
        obj_mapping = {obj.id: obj for obj in instance}
        data_mapping = {data['id']: data for data in validated_data}

        # Perform creations and updates.
        ret = []
        for data_id, data in data_mapping.items():
            obj = obj_mapping.get(data_id, None)
            if obj is None:
                ret.append(self.child.create(data))
            else:
                ret.append(self.child.update(obj, data))

        # Perform deletions.
        for obj_id, obj in obj_mapping.items():
            if obj_id not in data_mapping:
                obj.delete()

        return ret


class PayOrderSerializer(ModelSerializer):
    """付款单"""
    id = serializers.IntegerField(required=False)
    sale_order_name = serializers.CharField(source='sale_order.order_no', read_only=True)
    customer_name = serializers.CharField(source='sale_order.customer.name', read_only=True)
    person_name = serializers.CharField(source='person.name', read_only=True)
    account_name = serializers.CharField(source='acc_title.name', read_only=True)
    acc_type_name = serializers.CharField(source='account_type.account', read_only=True)
    user_name = serializers.CharField(source='user.real_name', read_only=True)
    flag_ok = serializers.BooleanField(source='flag', read_only=True)

    class Meta:
        model = PayOrder
        list_serializer_class = PayOrderListSerializer
        fields = [
            'id', 'order_no', 'order_time', 'sale_order', 'sale_order_name', 'customer_name', 'person',
            'person_name', 'desc', 'user', 'user_name', 'acc_title', 'account_name', 'account_type',
            'acc_type_name', 'money', 'flag', 'flag_ok'
        ]


class PayOrderCreateSerializer(ModelSerializer):
    """付款单"""
    person_name = serializers.CharField(source='person.name', read_only=True)

    class Meta:
        model = PayOrder
        fields = [
            'id', 'order_no', 'order_time', 'sale_order', 'person', 'person_name',
            'desc', 'user', 'acc_title', 'account_type', 'money', 'flag'
        ]


class BusinessFeeSerializer(ModelSerializer):
    """商务费"""

    class Meta:
        model = BusinessFee
        exclude = ['update_at', 'create_at']


class SaleOrderSerializer(ModelSerializer):
    """销售单"""
    customer_name = serializers.CharField(source='customer.name', read_only=True)
    account_name = serializers.CharField(source='acc_title.name', read_only=True)
    user_name = serializers.CharField(source='user.real_name', read_only=True)
    handler_name = serializers.CharField(source='handler.name', read_only=True)
    acc_type_name = serializers.CharField(source='account_type.account', read_only=True)
    receipts = ReceiptSerializer(many=True, read_only=True)
    pays = PayOrderSerializer(many=True, read_only=True)
    fees = BusinessFeeSerializer(many=True, read_only=True)
    debt = serializers.SerializerMethodField()
    lawyers = serializers.SerializerMethodField()
    assigned_money = serializers.SerializerMethodField()

    class Meta:
        model = SaleOrder
        exclude = ['update_at', 'create_at']

    def get_debt(self, obj):
        if obj.paid_money is None:
            return obj.recv_money
        return obj.recv_money - obj.paid_money

    def get_assigned_money(self, obj):
        """已分配利润"""
        totals = obj.pays.all().aggregate(total_money=Sum("money"))
        total_money = totals.get("total_money", 0)
        total_money = total_money if total_money else 0
        return total_money

    def get_lawyers(self, obj):
        return CaseLawyerListSerializer(obj.customer.lawyers.all(), many=True).data


class CaseLawyerListSerializer(ModelSerializer):
    """负责律师"""
    ratio = serializers.SerializerMethodField()

    class Meta:
        model = CaseLawyer
        fields = ["customer", "employee", "post", "ratio"]

    def get_ratio(self, obj):
        rule = ProfitRule.objects.filter(position=obj.post).first()
        return rule.ratio if rule else 0


class SaleOrderListSerializer(ModelSerializer):
    """销售单"""
    customer_name = serializers.CharField(source='customer.name', read_only=True)
    debt = serializers.SerializerMethodField()
    lawyers = serializers.SerializerMethodField()
    payments_base = serializers.SerializerMethodField()

    class Meta:
        model = SaleOrder
        fields = ['id', 'order_no', 'customer', 'customer_name', 'case_name', 'recv_money', 'paid_money', 'payment_money', 'telephone', 'debt', 'lawyers', 'payments_base']

    def get_debt(self, obj):
        if obj.paid_money is None:
            return obj.recv_money
        return obj.recv_money - obj.paid_money

    def get_lawyers(self, obj):
        return CaseLawyerListSerializer(obj.customer.lawyers.all(), many=True).data

    def get_payments_base(self, obj):
        result = obj.pays.filter(flag=True).aggregate(pre_paid_money=Sum('money'))
        pre_paid_money = result.get("pre_paid_money", 0)
        if pre_paid_money is None:
            pre_paid_money = 0
        return pre_paid_money


class ExpenseSerializer(ModelSerializer):
    """费用单"""
    acc_type_name = serializers.CharField(source='account_type.account', read_only=True)
    account_name = serializers.CharField(source='acc_title.name', read_only=True)

    class Meta:
        model = Expense
        fields = ['id', 'order_no', 'name', 'acc_title', 'account_type', 'acc_type_name', 'account_name', 'money', 'order_time', 'desc', 'user']


class ProfitRuleSerializer(ModelSerializer):
    """利润分配比例"""

    position_name = serializers.CharField(source='get_position_display', read_only=True)

    class Meta:
        model = ProfitRule
        fields = ['id', 'position', 'position_name', 'ratio']


class OtherIncomeSerializer(ModelSerializer):
    """其他收入"""
    account_name = serializers.CharField(source='acc_title.name', read_only=True)
    acc_type_name = serializers.CharField(source='account_type.account', read_only=True)

    class Meta:
        model = OtherIncome
        fields = ['id', 'order_no', 'name', 'acc_title', 'account_type', 'acc_type_name', 'account_name', 'money', 'order_time', 'desc', 'source', 'user']


class JournalSerializer(ModelSerializer):
    """流水账"""
    account_name = serializers.CharField(source='acc_title.name', read_only=True)
    order_type_name = serializers.CharField(source='get_order_type_display', read_only=True)
    user_name = serializers.CharField(source='user.real_name', read_only=True)
    oper_time = serializers.SerializerMethodField()

    class Meta:
        model = Journal
        exclude = ['update_at', 'create_at']

    def get_oper_time(self, obj):
        return obj.create_at.strftime('%Y-%m-%d %H:%M:%S')


class InitAccountSerializer(ModelSerializer):
    """初始建账"""

    class Meta:
        model = InitAccount
        exclude = ['update_at', 'create_at']


class BorrowLendSerializer(ModelSerializer):
    """借入借出"""
    person_name = serializers.CharField(source='person.name', read_only=True)
    category_name = serializers.CharField(source='get_category_display', read_only=True)
    acc_type_name = serializers.CharField(source='account_type.account', read_only=True)

    class Meta:
        model = BorrowLend
        exclude = ['update_at', 'create_at']


class RepaymentBillSerializer(ModelSerializer):
    """还款记录"""
    user_name = serializers.CharField(source='user.real_name', read_only=True)

    class Meta:
        model = RepaymentBill
        exclude = ['update_at', 'create_at']


class FundBillSerializer(ModelSerializer):
    """资金账单"""
    employee_name = serializers.CharField(source='employee.name', read_only=True)
    customer_name = serializers.CharField(source='customer.name', read_only=True)
    category_name = serializers.CharField(source='get_category_display', read_only=True)
    acc_type_name = serializers.CharField(source='account_type.account', read_only=True)
    title_name = serializers.CharField(source='acc_title.name', read_only=True)
    user_name = serializers.CharField(source='user.real_name', read_only=True)
    balance = serializers.SerializerMethodField(read_only=True)
    employee_customer = serializers.SerializerMethodField(read_only=True)
    repayments = RepaymentBillSerializer(many=True, read_only=True)

    class Meta:
        model = FundBill
        exclude = ['update_at', 'create_at']

    def get_balance(self, obj):
        return obj.money - obj.repayment

    def get_employee_customer(self, obj):
        emp_cust_name = obj.employee.name if obj.employee else '无'
        emp_cust_name = obj.customer.name if obj.customer else emp_cust_name
        return emp_cust_name





